﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using UnityEngine.UI;
using System;
using System.Linq;
using System.Net;
using System.Text;

public class Echo : MonoBehaviour
{
    // State object for receiving data from remote device.  
    public class StateObject
    {
        // Client socket.  
        public Socket workSocket = null;
        // Size of receive buffer.  
        public const int BufferSize = 256;
        // Receive buffer.  
        public byte[] buffer = new byte[BufferSize];
        // Received data string.  
        public StringBuilder sb = new StringBuilder();
    }

    //定义套接字
    Socket socket;
    //UGUI
    public InputField InputFeld;
    public Text text;
    //接收缓冲区
    ByteArray readBuff = new ByteArray();
    //发送缓冲区
    Queue<ByteArray> writeQueue = new Queue<ByteArray>();
    //显示文字
    string recvStr = "";

    public void Connection()
    {
        //Socket
        socket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);
        //为了精简代码：使用同步Connect
        //             不考虑抛出异常
        IPAddress ipAdr = IPAddress.Parse("127.0.0.1");
        IPEndPoint ipEp = new IPEndPoint(ipAdr, 8888);
        socket.Connect(ipEp);

        socket.BeginReceive(readBuff.bytes, readBuff.writeIdx, readBuff.remain, 0, ReceiveCallback, socket);
    }


    //点击连接按钮

    public void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            Socket socket = (Socket)ar.AsyncState;
            //获取接收数据长度
            int count = socket.EndReceive(ar);
            readBuff.writeIdx += count;
            //解析接收的数据
            OnReceiveData();
            //继续接收数据
            if (readBuff.remain < 8)
            {
                readBuff.MoveBytes();
                readBuff.ReSize(readBuff.length);//这里和原书不同
            }
            socket.BeginReceive(readBuff.bytes, readBuff.writeIdx, readBuff.remain, 0, ReceiveCallback, socket);
        }
        catch (SocketException ex)
        {
            Debug.Log("Socket Receive fail" + ex.ToString());
        }
    }
    public void OnReceiveData()
    {
        Debug.Log("[Recv 1] length  =" + readBuff.length);
        Debug.Log("[Recv 2] readbuff=" + ReadToString());
        if (readBuff.length <= 2) return;
        //如果是完整的就去处理它
        int readIdx = readBuff.readIdx;
        byte[] bytes = readBuff.bytes;
        //UInt16 bodyLength = BitConverter.ToUInt16(readBuff, 0);
        UInt16 bodyLength = (UInt16)((bytes[1] << 8) | bytes[0]);//小端模式解析
        Debug.Log("[recv] bodyLength=" + bodyLength);
        //判断消息体长度
        if (readBuff.length < bodyLength)
            return;
        readBuff.readIdx += 2;
        Debug.Log("[Recv 3] bodyLength=" + bodyLength);
        //消息体
        byte[] stringByte = new byte[bodyLength];
        readBuff.Read(stringByte, 0, bodyLength);
        string s = System.Text.Encoding.UTF8.GetString(stringByte);
        Debug.Log("[Rece 4]s=" + s);

        Debug.Log("[Recv 5] readbuff=" + ReadToString());
        //消息处理
        recvStr = s + "\n" + recvStr;
        //继续读取消息
        if (readBuff.length > 2)
        {
            OnReceiveData();
        }
    }
    
    //点击发送按钮
    public void Send()
    {
        string sendStr = InputFeld.text;
        //组装协议
        byte[] bodyBytes = System.Text.Encoding.UTF8.GetBytes(sendStr);
        UInt16 len = (UInt16)bodyBytes.Length;
        byte[] lenBytes = BitConverter.GetBytes(len);
        //大小端
        if (!BitConverter.IsLittleEndian)
        {
            Debug.Log("[Send] Reverse lenBytes");
            lenBytes.Reverse();
        }
        //把bodyBytes接在lenBytes的后面，并返回一个新得数组
        byte[] sendBytes = lenBytes.Concat(bodyBytes).ToArray();
        ByteArray ba = new ByteArray(sendBytes);
        lock (writeQueue)
        {
            writeQueue.Enqueue(ba);
        }
        if (writeQueue.Count == 1)
            socket.BeginSend(ba.bytes, ba.readIdx, ba.length, 0, SendCallback, socket);
        string s = SendToString();
        Debug.Log("[Send] " + s);
    }
    public void SendCallback(IAsyncResult ar)
    {

        //获取state
        Socket socket = (Socket)ar.AsyncState;
        //EndSend的处理
        int count = socket.EndSend(ar);
        Debug.Log("Socket Send succ " + count);
        ByteArray ba;
        lock (writeQueue)
        {
            ba = writeQueue.First();
        }
        ba.readIdx += count;
        if (ba.length == count)//发送完整
        {
            lock (writeQueue)
            {
                writeQueue.Dequeue();
                if (writeQueue.Count == 0)
                    ba = null;
                else ba = writeQueue.First();
            }
        }
        if (ba != null)
        {
            socket.BeginSend(ba.bytes, ba.readIdx, ba.length, 0, SendCallback, socket);
        }
    }
    public void Update()
    {
        text.text = recvStr;
    }
    public string SendToString()
    {
        ByteArray ba;
        if (writeQueue.Count > 0)
        {
            ba = writeQueue.First();
            Int16 ret = BitConverter.ToInt16(ba.bytes, ba.readIdx);
            string s = System.Text.Encoding.UTF8.GetString(ba.bytes, 2, ba.length - 2);
            return s = ret.ToString() + s;
        }
        return null;
    }
    public string ReadToString()
    {
        ByteArray ba;
        
        {
            ba = readBuff;
            Int16 ret = BitConverter.ToInt16(ba.bytes, ba.readIdx);
            string s = System.Text.Encoding.UTF8.GetString(ba.bytes, 2, ba.length - 2 < 0 ? 0 : ba.length - 2);
            return s = ret.ToString() + s;
        }
        //return null;
    }
}
